package controller;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLConnection;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 * Servlet implementation class AJAXcontroller
 */
public class AJAXcontroller extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public AJAXcontroller() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		String todo = request.getParameter("todo");
		HttpSession session = request.getSession(true);
		String traffyKey = (String) session.getAttribute("traffyKey");
		if(todo.equals("getLinkId")){
			
			String location = request.getParameter("location");
			String [] locationA = location.split(",");
			String lat = locationA[0].substring(1);
			String lng = locationA[1].substring(1, locationA[1].length()-1);
			
			if(traffyKey==null || traffyKey.equals(""))
				traffyKey = getTraffyKey(request, response);
			
			URL getLinkUrl = new URL("http://athena.traffy.in.th/apis/apitraffy.php?api=getLinkInfo&key="+traffyKey+"&appid=00001368&format=xml&radius="+lat+","+lng+",1000");
	        URLConnection getLinkCon = getLinkUrl.openConnection();
	        BufferedReader linkXML = new BufferedReader(new InputStreamReader(getLinkCon.getInputStream()));
	        String inputLine;
	        String linkId="";
	        while ((inputLine = linkXML.readLine()) != null){
				try {
					linkId += parseLinkInfoXML(inputLine);
				} catch (SAXException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (ParserConfigurationException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
	        }
	        PrintWriter writer = response.getWriter(); 
			writer.print(linkId.substring(1));
	        linkXML.close();
		}else if (todo.equals("getCL")) {
			String link = request.getParameter("link");
			System.out.println(link);
			if(traffyKey==null || traffyKey.equals(""))
				traffyKey = getTraffyKey(request, response);
			
			URL getLinkUrl = new URL("http://api.traffy.in.th/apis/apitraffy.php?format=XML&api=getCL&key="+traffyKey+"&appid=00001368&linkid="+link);
	        URLConnection getLinkCon = getLinkUrl.openConnection();
	        BufferedReader linkXML = new BufferedReader(new InputStreamReader(getLinkCon.getInputStream()));
	        String inputLine;
	        String clTxt="";
	        while ((inputLine = linkXML.readLine()) != null){
	        	if(!"<?xml version=\"1.0\"?>".equals(inputLine)){
					try {System.out.println("inputLine: "+inputLine);
						clTxt += parseCLXML(inputLine);
					} catch (SAXException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (ParserConfigurationException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
	        	}
	        }
	        System.out.println("clTxt: "+clTxt);
	        PrintWriter writer = response.getWriter();
	        if(!clTxt.equals("")){
	        	writer.print(clTxt.substring(2));
	        }else{
	        	writer.print(clTxt);
	        }
	        linkXML.close();
		}else if(todo.equals("getRainForecast")){
			String location = request.getParameter("location");
			String [] locationA = location.split(",");
			String lat = locationA[0].substring(1);
			String lng = locationA[1].substring(1, locationA[1].length()-1);
			
			if(traffyKey==null || traffyKey.equals(""))
				traffyKey = getTraffyKey(request, response);
			
			BufferedReader rainXML;
			try{
				URL getRainUrl = new URL("http://athena.traffy.in.th/apis/apitraffy.php?api=getRainForecast&key="+traffyKey+"&appid=00001368&format=xml&location="+lat+","+lng+"&type=1&pt=30");
		        URLConnection getRainCon = getRainUrl.openConnection();
		        getRainCon.setReadTimeout(60000); //30 seconds
		        rainXML = new BufferedReader(new InputStreamReader(getRainCon.getInputStream()));
		        String inputLine;
		        String rainStatus="";
		        String resultXML="";
		        while ((inputLine = rainXML.readLine()) != null){
		        	resultXML+=inputLine;
		        }
	        	rainStatus = parseRainXML(resultXML);
	        	PrintWriter writer = response.getWriter(); 
	 			writer.print(rainStatus);
	 			rainXML.close();
			} catch(SocketTimeoutException e){
				// TODO Auto-generated catch block
				e.printStackTrace();
				System.out.println("Time out, so use defualt: 'no rain'");
				PrintWriter writer = response.getWriter(); 
				writer.print("0");
//				rainXML.close();
			}catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				System.out.println("Exception occured, so use defualt: 'no rain'");
				PrintWriter writer = response.getWriter(); 
				writer.print("0");
//				rainXML.close();
			}
		}
	}

	private String getTraffyKey(HttpServletRequest request, HttpServletResponse response) {
		// TODO Auto-generated method stub
		String appid = "00001368";
		String keytext = "";
		String hiddenkey = "AibgZsBJdV";
		URL getKeyUrl;
		String passkey="";
		try {
			getKeyUrl = new URL("http://api.traffy.in.th/apis/getKey.php?appid=" + appid);
			URLConnection getKeyCon = getKeyUrl.openConnection();
	        BufferedReader key = new BufferedReader(new InputStreamReader(getKeyCon.getInputStream()));
	        
			keytext = key.readLine();
			
			passkey = encodeString(appid+keytext.trim()) + encodeString(hiddenkey+keytext.trim());
			
			HttpSession session = request.getSession(true);
			session.setAttribute("traffyKey", passkey);
		} catch (MalformedURLException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return passkey;
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
	}
	
	public String encodeString(String txt) throws NoSuchAlgorithmException, UnsupportedEncodingException  { 
    	// Use MD5
        MessageDigest md;
        md = MessageDigest.getInstance("MD5");
        byte[] md5hash = new byte[32];
        md.update(txt.getBytes("iso-8859-1"), 0, txt.length());
        md5hash = md.digest();
        return convertToHex(md5hash);
    } 
    
    private static String convertToHex(byte[] data) { 
        StringBuffer buf = new StringBuffer();
        for (int i = 0; i < data.length; i++) { 
            int halfbyte = (data[i] >>> 4) & 0x0F;
            int two_halfs = 0;
            do { 
                if ((0 <= halfbyte) && (halfbyte <= 9)) 
                    buf.append((char) ('0' + halfbyte));
                else 
                    buf.append((char) ('a' + (halfbyte - 10)));
                halfbyte = data[i] & 0x0F;
            } while(two_halfs++ < 1);
        } 
        return buf.toString();
    } 
    
    public String parseLinkInfoXML(String linkXML) throws SAXException, IOException, ParserConfigurationException{
    	String linkId = "";
    	if(!linkXML.equals("Information Not Available")){
	    	DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
	        DocumentBuilder db = dbf.newDocumentBuilder();
	        InputSource is = new InputSource();
	        is.setCharacterStream(new StringReader(linkXML));
	
	        Document doc = db.parse(is);
	        NodeList nodes = doc.getElementsByTagName("linkinfo");
	
	        // Get only one linkId
	        for (int i = 0; i < nodes.getLength(); i++) {
	           Element element = (Element) nodes.item(i);
	
	           linkId += ","+element.getAttribute("linkid");
	        }
	    }else{
	    	linkId = "0";
	    }
    	
    	return linkId;
    }
    
    public String parseCLXML(String clXML) throws SAXException, IOException, ParserConfigurationException{
    	String cl = "";
//    	if(!linkXML.equals("Information Not Available")){
	    	DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
	        DocumentBuilder db = dbf.newDocumentBuilder();
	        InputSource is = new InputSource();
	        is.setCharacterStream(new StringReader(clXML));
	
	        Document doc = db.parse(is);
	        NodeList nodes = doc.getElementsByTagName("trafficmessage");
	
	        // Get only one linkId
	        for (int i = 0; i < nodes.getLength(); i++) {
	           Element element = (Element) nodes.item(i);
	           String txt = getTextValue(element, "status");
	           if(txt!= null)
	        	   cl += "##"+txt;
	        }
//	    }else{
//	    	linkId = "0";
//	    }
    	
    	return cl;
    }

    
    public String parseRainXML(String rainXML) throws SAXException, IOException, ParserConfigurationException{
    	System.out.println("rainXML: "+rainXML);
    	String rain = "";
//    	if(!linkXML.equals("Information Not Available")){
	    	DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
	        DocumentBuilder db = dbf.newDocumentBuilder();
	        InputSource is = new InputSource();
	        is.setCharacterStream(new StringReader(rainXML));
	        
	        Document doc = db.parse(is);
	        NodeList nodes = doc.getElementsByTagName("report");
	
	        // Get only one linkId
	        for (int i = 0; i < nodes.getLength(); i++) {
	           Element element = (Element) nodes.item(i);
	
	           rain += element.getAttribute("rain");
	        }
//	    }else{
//	    	linkId = "0";
//	    }
    	System.out.println(rain);
    	return rain;
    }
    
    private String getTextValue(Element ele, String tagName) {
		String textVal = null;
		NodeList nl = ele.getElementsByTagName(tagName);
		if(nl != null && nl.getLength() > 0) {
			Element el = (Element)nl.item(0);
			textVal = el.getFirstChild().getNodeValue();
		}

		return textVal;
	}
}
